﻿#region

using System;
using System.Collections.Generic;
using System.Linq;
using SFMLStart.Utilities;

#endregion

namespace VeeTileEngine2012
{
    public class Field
    {
        public Field() { TileManager = new TileManager(this); }

        private TileManager TileManager { get; set; }
        public int Width { get { return TileManager.Width; } }
        public int Height { get { return TileManager.Height; } }
        public Action<Entity> OnEntityAdded { get; set; }
        public Action OnTurnStart { get; set; }
        public Action OnTurn { get; set; }
        public Action OnTurnChecks { get; set; }
        public Action OnTurnFinished { get; set; }

        public void Clear(int mWidth, int mHeight) { TileManager.Clear(mWidth, mHeight); }

        public Tile[,] GetTiles() { return TileManager.Tiles; }
        public Tile GetTile(int mX, int mY) { return !IsTileValid(mX, mY) ? null : TileManager.GetTile(mX, mY); }
        public Entity GetEntityOnTop(int mX, int mY) { return GetTile(mX, mY).OrderedEntities.Last(); }
        public IEnumerable<Entity> GetEntities() { return TileManager.Repository.GetEntities(); }
        public IEnumerable<Entity> GetEntitiesByTag(string mTag) { return TileManager.Repository.GetEntities(mTag); }
        public IEnumerable<Entity> GetEntitiesByComponent(Type mType) { return TileManager.Repository.GetEntitiesByComponent(mType); }
        public IEnumerable<Component> GetComponents(Type mType) { return TileManager.Repository.GetComponents(mType); }
        public IEnumerable<Entity> GetEntities(int mX, int mY) { return GetTile(mX, mY).Repository.GetEntities(); }
        public IEnumerable<Entity> GetEntitiesByTag(int mX, int mY, string mTag) { return GetTile(mX, mY).Repository.GetEntities(mTag); }
        public IEnumerable<Entity> GetEntitiesByComponent(int mX, int mY, Type mType) { return GetTile(mX, mY).Repository.GetEntitiesByComponent(mType); }
        public IEnumerable<Component> GetComponents(int mX, int mY, Type mType) { return GetTile(mX, mY).Repository.GetComponents(mType); }
        public bool IsTileValid(int mX, int mY) { return TileManager.IsValid(mX, mY); }
        public bool HasEntityByTag(int mX, int mY, string mTag, Func<Entity, bool> mCondition = null) { return IsTileValid(mX, mY) && GetTile(mX, mY).Repository.GetEntities(mTag).Any(x => mCondition == null || mCondition.Invoke(x)); }
        public bool HasEntityByComponent(int mX, int mY, Type mType, Func<Entity, bool> mCondition = null) { return IsTileValid(mX, mY) && GetTile(mX, mY).Repository.GetEntitiesByComponent(mType).Any(x => mCondition == null || mCondition.Invoke(x)); }

        public void AddEntity(Entity mEntity)
        {
            mEntity.OnAddedToField.SafeInvoke();
            OnEntityAdded.SafeInvoke(mEntity);
        }

        public void TurnStart() { OnTurnStart.SafeInvoke(); }
        public void TurnChecks() { OnTurnChecks.SafeInvoke(); }
        public void TurnFinished() { OnTurnFinished.SafeInvoke(); }

        public void NextTurn(object mInput = null)
        {
            OnTurnStart.SafeInvoke();
            TileManager.NextTurn(mInput);
            OnTurn.SafeInvoke();
            OnTurnChecks.SafeInvoke();
            OnTurnFinished.SafeInvoke();
        }
    }
}